{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "8e685dc4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 和房价有关的一些参数（面积，位置，房间布局）\n",
    "import numpy as np\n",
    "\n",
    "from sklearn import datasets\n",
    "\n",
    "from sklearn.linear_model import LinearRegression"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "03f39655",
   "metadata": {},
   "source": [
    "#### 1.1 加载数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "306cfed8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD',\n",
       "       'TAX', 'PTRATIO', 'B', 'LSTAT'], dtype='<U7')"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "boston = datasets.load_boston()\n",
    "\n",
    "# 数据，影响房价的列\n",
    "X = boston['data']\n",
    "# 房价（万美金）\n",
    "y = boston['target']\n",
    "\n",
    "# 房价具体特征，具体指标\n",
    "# CRIM犯罪\n",
    "# NOX空气污染\n",
    "# TAX税收\n",
    "feature_names = boston['feature_names']\n",
    "feature_names"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ec617c39",
   "metadata": {},
   "source": [
    "#### 1.2 数据查看"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "56b66b7a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(506, 13)"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 506表示506统计样本\n",
    "# 13表示影响房价的13个属性\n",
    "X.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "cdc0c22f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(506,)"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 506个房子，对应着506个价格\n",
    "# X ----> y 一一对应\n",
    "# 数据 ---> 目标值对应\n",
    "y.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5ea60046",
   "metadata": {},
   "source": [
    "#### 1.3 数据拆分"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "b562d575",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 506个数据样本\n",
    "# 拆分成两份：80%的训练数据、20%的验证数据\n",
    "# 拿出其中80%，交给算法，线性回归，学习、总结、拟合函数\n",
    "index = np.arange(506)\n",
    "np.random.shuffle(index)\n",
    "train_index = index[:405]\n",
    "test_index = index[405:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "b35e5bf4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(405, 13)"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "(405,)"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 80%的训练数据\n",
    "X_train = X[train_index]\n",
    "y_train = y[train_index]\n",
    "display(X_train.shape, y_train.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "b36800bf",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(101, 13)"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "(101,)"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 20%的测试数据\n",
    "X_test = X[test_index]\n",
    "y_test = y[test_index]\n",
    "display(X_test.shape, y_test.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "123ac84e",
   "metadata": {},
   "source": [
    "#### 1.4 数据建模"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "90013abf",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ -0.11505289,   0.04627326,   0.00824638,   2.09344912,\n",
       "       -20.55699794,   3.41372332,   0.01037575,  -1.49392435,\n",
       "         0.30590903,  -0.01202509,  -1.02437249,   0.00842463,\n",
       "        -0.52202987])"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "41.52593211873281"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "array(['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD',\n",
       "       'TAX', 'PTRATIO', 'B', 'LSTAT'], dtype='<U7')"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# numpy打印输出不使用科学计数法\n",
    "np.set_printoptions(suppress=True)\n",
    "\n",
    "# 允许已有的截距\n",
    "model = LinearRegression(fit_intercept = True)\n",
    "\n",
    "# 如何模型\n",
    "model.fit(X_train, y_train)\n",
    "\n",
    "# 建模生成了斜率\n",
    "# 正：正相关，负：负相关\n",
    "display(model.coef_, model.intercept_)\n",
    "\n",
    "feature_names"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f00493df",
   "metadata": {},
   "source": [
    "#### 1.5 模型验证"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "66dbe2d7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([24.3 , 24.81, 26.13, 37.47, 21.24, 22.76, 20.21,  5.95, 31.55,\n",
       "       34.75, 35.29, 19.84, 28.02, 28.86, 19.97, 30.88, 18.74, 24.93,\n",
       "       22.32, 13.36, 39.03, 17.35, 19.04, 16.81, 15.61, 22.26, 19.55,\n",
       "       28.16, 20.12, 21.63])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 模型预测的结果 y_\n",
    "y_ = model.predict(X_test).round(2)\n",
    "\n",
    "y_[:30]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "b77df79a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([24.7, 23.9, 22.2, 41.7, 21.2, 24.7, 17.1,  8.8, 29.9, 33.8, 32.4,\n",
       "       13.3, 36.2, 25. , 19.4, 31.5, 14.1, 24.7, 22.4, 15.6, 43.5, 13.9,\n",
       "       16. , 14.9, 14.1, 11.9, 15.3, 31.2, 27.1, 20.1])"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 标价\n",
    "y_test[:30]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1e222256",
   "metadata": {},
   "source": [
    "#### 1.6 模型评估"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "6e0886a5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.7130961607475034"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 评分最大值为1，可以小于0\n",
    "model.score(X_test, y_test)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d38560da",
   "metadata": {},
   "source": [
    "$\n",
    "R^{2} = 1 - \\frac{u}{v}\n",
    "$\n",
    "\n",
    "u is the residual sum of squares ((y_true - y_predict) ** 2).sum()\n",
    "\n",
    "v is the total sum of squares ((y_true - y_true.mean()) ** 2).sum()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "595b01b4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# y_true 对应 y_test，保留20%的房价数据；y_pred 对应算法，计算出来的结果\n",
    "y_pred = model.predict(X_test)\n",
    "y_true = y_test"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "7cdc829b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2550.903053521064"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "u = ((y_true - y_pred) ** 2).sum()\n",
    "u"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "51acfdb0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "8891.142970297029"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "v = ((y_true - y_true.mean()) ** 2).sum()\n",
    "v"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "fae9de24",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.7130961607475034"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 评价指标，越接近1，说明算法越优秀\n",
    "1 - u/v"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "ed4a7f3f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 其他的模型评估\n",
    "# 最小二乘法\n",
    "from sklearn.metrics import mean_squared_error"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "036a777b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "25.25646587644618"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 这个是测试数据，验证数据，表现，误差\n",
    "# 对应20%测试集\n",
    "mean_squared_error(y_true, y_pred)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "22c0dba4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "21.22441105342588"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 80%训练表现，误差（训练集误差更小）\n",
    "mean_squared_error(y_train, model.predict(X_train))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f8cfdc35",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
